<?php
namespace Admin\Model;
use Think\Crypt\Driver\Think;
use Think\Model;
class CategoryModel extends Model{
    protected $insertFields = 'cat_name,parent_id,is_floor';
    protected $updateFields = 'id,cat_name,parent_id,is_floor';
    protected $_validate = array(
        array('cat_name', 'require', '分类名称不能为空！', 1, 'regex', 3),
    );

    /***********找一个分类所有子分类的ID************/
    public function getChilder($catId){
        //找分类的所有子分类 要先找到分类表里的所有分类才行  用递归 核心
        $data =$this->select();
        //递归中所有分类中挑出子分类

        //把查出来的分类结果赋值给递归函数的第一个参数（从所有分类里找） 传进来的id作为需要查找的子分类id
        return $this->_getChilder($data,$catId,TRUE);  //返回找到的值      第三个参数赋值给递归函数的第三个参数 让静态数组清空第一次保留后的数据
    }
    //在定义一个递归的函数
    //里面传俩个参数
    //从哪个分类里找(在getChilder里查出来的就是) 找哪个分类的子分类
    //递归从数据中找子分类
    private function _getChilder($data,$catId,$isClear = FALSE){   //默认不为真
/********************这里不能不用静态修饰***********************/
        static $_ret = array();  //定义一个数组  保存找到的子分类！ 把从顶级分类里找到对应的子分类 找到一个放进去一个
/***********判断数组是否要清空******** 如果不清空砸同一个脚本调用多次这个函数 那么该数组会保留之前存放在数组中的值  因为它是一个静态变量*******/
        if($isClear){
            $_ret=array();                                                  //在函数给的第三个变量判断是否为真 若为真就情况数组 如果不为真数组里的数保留
        }
        //循环所有的分类找子分类
        foreach($data as $k => $v){
            if($v['parent_id'] == $catId){                                    //如果某一个或者某几个id后面的parent—id 等于传进来的id  你们这个分类id 就是传进来id的子分类
                $_ret[] = $v['id'];                              //单独拿出所有的id和子id
//                再找$v下面的子分类
                $this->_getChilder($data,$v['id']);
            }
        }
        return $_ret;// 找到之后返回
    }


    /***********打印树形结构图****************/
    public function getTree(){
        $data = $this->select();                                                //获得无限极分类里的所有分类数据
        return $this->_getTree($data);                                         // 传入递归函数  从顶级分类开始找，0默认为顶级分类
    }
/***************打印树形图递归*********************/
    private function _getTree($data,$parent_id=0,$level=0){                   //$level 为了方便标记分类级别  因为数据库中的顶级分类都是0 所有查找0下面的id
       static $_ret = array();
        foreach ($data as $k =>$v){
            if( $v['parent_id'] == $parent_id){                                   //parent传进来的是等于0 的 所有0 就是顶级分类！
                $v['level'] = $level;                                            //用于标记这个分类时第几级
                $_ret[] = $v;                                                    //如果相等 就把这个id的值放到数组中去 后期取出 如果相等表示它是顶级的
                //找子分类
                $this->_getTree($data ,$v['id'],$level+1);                       //还是从所有数据中找 但是这里要找$v的id对应的下面的所有分类
                // 如果查到然后第三个参数等级要加一 表示当前id的下级的N级分类
            }
        }
        return $_ret;           //返回所有数据
    }


    /********删除之前先找出所有子分类的id**********************/
    protected function _before_delete($option){
        $id = $option['where']['id'];
        $Childer = $this->getChilder($id);
        if($Childer){

            //如果有子分类 就把数组转化成字符串  这里的是一个一位数组
            $Childer = implode(',',$Childer);
            //删除这些子类的id
            //$this->delete($Childer);这么写会有问题 因为这里面是一个字符串 删除的时候回条用beforedelete 这个函数 可能导致死循环  删一次调用钩子函数一次
            //最好的办法就是用父类模型去调用删除（delete）
            $molde = new\Think\Model();
            $molde->table('__CATEGORY__')->delete($Childer);   //用父类删除   指定那张表 因为分类不知道你删的是那张表
        }
    }


    /*************************************************************前台模型放后台**************************************************************************/
    /*************************************************************前台模型放后台**************************************************************************/
    /*************************************************************前台模型放后台**************************************************************************/
    /*************************************************************前台模型放后台**************************************************************************/

    public function getdht(){
        $catData = S('$catData');
        if(!$catData) {
            $allcat = $this->select();//先取出所有的分类  没办法加limit
            //定义一个空数组 放顶级分类
            $ret = array();
            foreach ($allcat as $v) {
                if ($v['parent_id'] == 0) {
                    foreach ($allcat as $v1) {
                        if ($v1['parent_id'] == $v['id']) {
                            foreach ($allcat as $v2) {
                                if ($v2['parent_id'] == $v1['id']) {         //这个是孙子分类
                                    $v1['children'][] = $v2;
                                }
                            }
                            $v['children'][] = $v1;      //你们这条信息 就是上级id的子分类
                            // （在上级分类里添加一个children下表的数组 专存子分类 同理孙子分类一样这么寸）
                            // 因为这个子分类看到不只有一个 所以这个children下表后面需要再加一个下表为自动的数字下表“【】” 不然后一个会把前一个覆盖
                        }
                    }
                    $ret[] = $v;  // 是顶级的就单独提出来
                }
            }
            S('catData',$ret,86400);
            return $ret;                //如果没有缓存把数据取出来 放到catdata里面 缓存这里是一天时间的秒数
        }else{
            return $catData;   // 如果有缓存 就直接把这个数据返回
        }

    }

    /**
     * 获取推荐大类的的信息 展示到前台
     */
    public function getFloor()
    {

        $FloorData = S('floorData');
        if(!$FloorData) {
            $goodsModel = D('Admin/Goods');
            //先取出所有被推荐的分类 首先判断这个必须是顶级的 而且还是推荐的
            $ret = $this->where(array(
                'parent_id' => array('eq', 0),
                'is_floor' => array('eq', '是'),
            ))->select();

            /*************循环每个推荐的二级分类 取出未推荐的二级分类并保存到这个顶级分类的subcat字段里*******************/
            foreach ($ret as $k => $v) {
                /*****************************************取出分类下商品的品牌logo************************************************/
                $ret[$k]['brand'] = $goodsModel->alias('a')
                    ->field('a.brand_id,b.logo')
                    ->join('LEFT JOIN __BRAND__ b ON a.brand_id = b.id')
                    ->where(array(
                        'a.cat_id' => array('eq', $v['id']),
                        'a.brand_id' => array('neq', 0)
                    ))
                    ->limit(9)
                    ->select();

                $ret[$k]['subCat'] = $this->where(array(
                    'parent_id' => array('eq', $v['id']),
                    'is_floor' => array('eq', '否'),
                ))->select();
            }

            /*************循环每个推荐的二级分类 取出推荐的二级分类并保存到这个顶级分类的recSubCat字段里*******************/
            foreach ($ret as $k => $v) {
                $ret[$k]['recSubCat'] = $this->where(array(
                    'parent_id' => array('eq', $v['id']),
                    'is_floor' => array('eq', '是'),
                ))->limit(5)->select();
            }

            /*************循环每个推荐的二级分类 取出推荐的二级分类下的商品   有点难度 *******************/
            foreach ($ret[$k]['recSubCat'] as $k1 => &$v1) {
//            $ret[] =$v1['id'];         //这里id正常 是二级分类的id
                // 这个函数取出所有分类 子分类 和拓展分类下的商品id  （在goods模型下）
//           $gid =  $goodsModel->getGoodesIdBYCatId($v1['id']);
                //第二步取出这些商品id下的所有商品信息 展示到页面
                $v1['goods'] = $goodsModel->field('id,goods_name,mid_logo,shop_price')->where(array(
                    'is_on_sale' => array('eq', '是'),         //必须是上架的
                    'is_floor' => array('eq', '是'),            //必须是推荐的
                    'cat_id' => array('eq', $v1['id']),
                ))->order('sort_num ASC')->limit(8)->select(); //根据排序的

            }
            S('floorData',$ret,86400);//这个意思就是 当没有缓存的时候 执行这里的代码最后把数据赋值给floorData 并且保存一天的时间
            return $ret;
            // 这个函数取出所有分类 子分类 和拓展分类下的商品id  （在goods模型下）
//        $ret = array();
//        $gid =  $goodsModel->getGoodesIdBYCatId(2);
//        //第二步去除这些商品id下的所有商品信息 展示到页面
//        $ret['goods'] =  $goodsModel->field('id,mid_logo,shop_price')->where(array(
//            'is_on_sale'=>array('eq','是'),         //必须是上架的
//            'is_floor'=>array('eq','是'),            //必须是推荐的
//            'id'=>array('in',$gid),
//        ))->order('sort_num ASC')->select(); //根据排序的
//        return $ret;
//    }
//        $ret['goods'] =  $goodsModel->field('id,goods_name,mid_logo,shop_price')->where(array(
//            'is_on_sale'=>array('eq','是'),         //必须是上架的
//            'is_floor'=>array('eq','是'),            //必须是推荐的
//            'cat_id'=>array('eq',4),
//        ))->order('sort_num ASC')->select(); //根据排序的
//        return $ret;
//
        }else{
            return $FloorData;   // 如果有缓存就换回这个变量 如果没有缓存就执行上面的代码
        }
    }

    /*********************找到这个分类的所有上级分类***************************/

    public function parentPath($catId){
        static $rec = array();
        $info = $this->field('id,cat_name,parent_id')->find($catId); //一维
        $rec[] = $info;
        //判断如果还有上级分类 就再次递归取出来
        if($info['parent_id'] > 0){
            $this->parentPath($info['parent_id']);
        }
        return $rec;
    }



    /*************************根据分类ID取出筛选条件**************************/
    public function getSearchConditionByCatId($catId){

        $ret = array();
        //根据商品id取出品牌id
        $goodModel = D('Admin/Goods');
        //根据传过来的分类id 得到这个分类下的所有品牌id
        $goodsId =  $goodModel->getGoodesIdBYCatId($catId);
        /***************** 分类下有哪些品牌可以搜索 ************************/
        $ret['brand'] = $goodModel->alias('a')
            ->field('DISTINCT b.brand_name,a.brand_id,b.logo')
            ->join('LEFT JOIN __BRAND__ b ON a.brand_id = b.id')
            ->where(array(
                'a.id' => array('in', $goodsId),
                'a.brand_id' => array('neq', 0)
            ))
            ->select();
        /***************** 价格区间段 ************************/
        $sectionCount = 6;             //默认分6段
        $priceInfo = $goodModel->field('MAX(shop_price) max_price,MIN(shop_price) min_price')->where(array(
            'id'=>array('in',$goodsId),
        ))->find();
        //得到最大价和最小价的区间
        $priceSection = $priceInfo['max_price'] - $priceInfo['min_price'];

        //查看有多少商品 如果只有一个俩个 就不用分6段
        $goods_count = count($goodsId);//全面取得id是一个数组  查看这个数组的长度就最大商品的数量  一个id是一个商品

        //只有商品数量满足这个多的时候才去分段
        if($goods_count > 6){
            //根据商品最大价和最小价差值计算分几段
            if($priceSection < 100){
                $sectionCount = 1;
            }elseif($priceSection < 1000){
                $sectionCount = 4;
            }elseif($priceSection < 10000){
                $sectionCount = 6;
            }else{
                $sectionCount = 7;
            }
            $pricePerSection = ceil($priceSection/$sectionCount);             //差价除以总段数 等于每一段的价格
            $price  = array();
            $firstPrice = $priceInfo['min_price'];                               //最小价格
            for($i=0;$i<$sectionCount;$i++){
                $price[] = $firstPrice.'-'.($firstPrice + $pricePerSection);       //第一段的价格是 最小价到最小价加上区间价
                $firstPrice = ($firstPrice + $pricePerSection + 1);              //第二个价格 最小价 加上区间价 加1 赋给最小价 这样就可以循环
                // 把新的最小价赋给上面的$firstPrice
                $ret['price'] = $price;
            }

        }
        /***************** 分类下有哪些品牌可以搜索 ************************/
        //根据得到的商品id 查找类型名称 和商品属性值
        $gaModel = D('goods_attr');
       $gaData =  $gaModel->alias('a')
            ->field('DISTINCT a.attr_id,a.attr_value,b.attr_name')
            ->join('LEFT JOIN __ATTRIBUTE__ b ON a.attr_id = b.id')
            ->where(array(
                'a.goods_id'=>array('IN',$goodsId),
            ))->select();

        //放之前 先把二维转三维 根据类型的名称做下标  因为我需要类型的名称循环出来
            $ga_Data =array();
        foreach($gaData as $k=>$v){
            $ga_Data[$v['attr_name']][] = $v;
        }
        //放到数组中
        $ret['gaData'] = $ga_Data;
        return $ret;
    }
}